JavaScript Customizations for Collections

Collections group together related sets of fields on a form, making it easy to repeat those sets. Addresses are a very common kind of collection, as they normally consist of several fields that always go together. In this section, we explain how you can determine the selectors you need for customizations on collections, and provide examples of some common customizations.

Selectors

The region taken up by the entire collection is a li element with a name and id in the format qN (q67 in the example below). The class of this element is cf-collection-block, which distinguishes the collection from other field types. The following screenshot shows the area occupied by a collection with two fields that are repeated. The li element representing the element is highlighted in blue in the right pane.

The HTML element corresponding to a collection.

Within the li element that comprises the entire collection, we have the following elements:

We will focus on how to select elements within the latter element. Within this element, we have div elements of class form-q. Each of these represents a set of fields—in our example, a pair of fields "Apples and Oranges" and "Just Apples". Our example has two sets in the collection, so there are two div elements with class form-q.

The HTML element corresponding to a set of fields in a collection.

Now we expand these class form-q elements to examine their inner structure. Both fields are contained in an unordered list element (ul) with the class rpx. Each field is represented by a li element with one part corresponding to the field label container and another to the input box container. The structure of each field is the same as that of conventional fields. Each field is wrapped in a field container with an ID of the format qN. In a collection with repeating sets of fields, this ID will not be unique—for example, all "Just Apples" field containers in our collection will have the same id, q72.

The HTML element corresponding to an individual field in a set of fields, within a collection.

For fields in collections, input boxes also have different ID assignment rules compared to conventional fields. To aid users in determining the patterns of these IDs, we have labeled each input box in our sample collection with its corresponding id:

Sample collection with each field labelled with its ID.

The format for fields in collections with repeating sets is FieldN(setNumber). With each additional set, the FieldN prefixes stay the same, but the setNumbers increment by one.

Reusing Inputs for Repeating Sets

When you have repeating sets of fields in a collection, you may want certain fields in later sets to be automatically filled with the values of their counterparts in previous sets. The following animation shows the desired behavior, as applied to the "Just Apples" field in the collection:

The following JavaScript snippet implements this customization.

$(document).ready(function() {
  $('a[ref-id="q20"]').click(function() { //after "Add" button is clicked
    var setCount = $(".cf-collection-block .rpx").length; //count number of repeating sets
    var newfieldid = "Field72(" + setCount + ")"; //id of "Just Apples" field that was just added
    var oldfieldid = "Field72(" + (setCount-1) + ")"; //id of previous "just Apples" field
    //set value of new field to value of previous field
    $('input[id="' + newfieldid + '"]').val($('input[id="' + oldfieldid + '"]').val());
  });
});

When the document is loaded, the browser waits for a click on the "Add" button, which has the attribute ref-id equal to q20.

The HTML element corresponding to the "Add" button in a collection with a dynamic number of sets.

After the click occurs, the following operations take place:

The HTML element corresponding to the field in a collection whose value should be copied to the same field in later sets.

Reusing Inputs Conditional on a Checkbox

Sometimes, you may want the automatic filling in the previous example to occur only when a box is checked. This is common, for instance, in online transactions where one has to specify a billing address and a shipping address. To save users time, you can have them check a box to indicate that the second address is the same as the first address. The collection corresponding to the second address will then be automatically filled with the values from the first collection.

The desired behavior is something like the following:

The JavaScript we used to implement this is as follows. It assumes that the Billing Address collection has been assigned the custom class billing, the Shipping Address has been assigned the custom class shipping, and the checkbox has been assigned the class sameAddress.

$(document).ready(function () { 
  $('.sameAddress').change(function() { //checks for changes in the checkbox
    if ($(this).find('input[value="Yes"]').is(':checked')) {
      //make list of all inputs in Shipping Address collection
      var shippingAddress = $('.shipping').find('input');
      //make list of all inputs in Billing Address collection 
      var billingAddress = $('.billing').find('input');
      //make list of all dropdown choices in Shipping Address collection
      var shippingDropdowns = $('.shipping').find('select');
      //make list of all dropdown choices in Billing Address collection
      var billingDropdowns = $('.billing').find('select');
      for (i=0; i<3; i++) { //iterate over the max. number of fields for each field type
        $(shippingAddress[i]).val($(billingAddress[i]).val()); //copy text inputs
        $(shippingDropdowns[i]).val($(billingDropdowns[i]).val()); //copy dropdown choices
      }
    }
  });
});

The code works as follows. When the document is loaded, the browser waits for changes made to the checkbox that indicates whether the shipping address is the same as the billing address. When a change occurs, the browser does the following if the checkbox is selected:

In this particular example, the duplication operation is slightly more complicated because we have both text inputs and drop-down menus in the address collections. Text input elements are of the type input, while drop-down menus are of the type select, so we made separate lists for each type. If you use the default address collection provided in the form designer's Layout page, you can eliminate the additional lines that handle the drop-down fields.

Targeting the Same Fields in Every Set

In some situations, two fields in a set may be systematically related, such that every set added to that collection should obey that relationship. To enforce this, you may want to carry out the same JavaScript operation in every set within a repeating collection. In the following example, we have repeating sets where we want "Not Applicable" to be filled in whenever "No" is selected in the previous field.

Our desired behavior is shown in the following animation:

We implement this using the following JavaScript snippet. The code assumes that you have assigned the custom class reportInfo to the collection and that the id of the "Reviewer" field is q58.

$(document).ready(function () {
  $('.reportInfo').on('change', '[type="radio"]', reqChange);


  function reqChange() {
    $('.reportInfo .rpx .radio-checkbox-fieldset').each(function () {
      $(this).find('input:checked').each(function() {
        if ($(this).val() == "No") {
          var reviewerField = $(this).closest('.rpx').find('[name="q58"]');
          $(reviewerField).find('input').val('Not Applicable');
        }
      })
    })
  }
})

When the document has loaded, the browser waits for a change in the radio buttons in the collection. When a change happens, the function reqChange is called. This function loops through every set of Yes/No radio buttons ($('.reportInfo .rpx .radio-checkbox.fieldset') selects for these sets) and does the following: